

#include "anotc_protocol.h"

//---------------------------------------------
#define MOUDLE_ANOTCFRAME_ENABLE
#ifdef MOUDLE_ANOTCFRAME_ENABLE

#define ANOTC_RESPONSE_TIMEOUT 250    // Timeout in ms

uint8_t data1, data2, data3;
void    Anotc_ProcessReceivedData(UART_t *UARTx);

uint8_t Anotc_ProcessSentData(UART_t *UARTx, uint8_t count) {

    // Check if UARTx or UARTx->tx_buffer is NULL
    if (UARTx == NULL) {
        return 0;
    }
    data1 += 2;
    data2 += 5;
    data3 -= 5;

    UARTx->tx_buffer[count++] = data1;
    UARTx->tx_buffer[count++] = data2;
    UARTx->tx_buffer[count++] = data3;

    return count;
}
/**
 * @brief Write an Anotc frame to UART.
 *
 * @param UARTx Pointer to a UART_t structure that contains the configuration information for the UART.
 */
void Anotc_WriteFrame(UART_t *UARTx) {
    uint8_t sumcheck = 0;
    uint8_t addcheck = 0;
    uint8_t i;
    uint8_t cnt = ANOTC_PROTOCOL_HEADER_SIZE;

    // Check if UARTx or UARTx->tx_buffer is NULL
    if (UARTx == NULL || UARTx->tx_buffer == NULL) {
        return;
    }
    if (UARTx->tx_bBusy) {
        return;
    }
    // Initialize protocol header
    UARTx->tx_buffer[0] = ANOTC_FRAME_HEADER;
    UARTx->tx_buffer[1] = ANOTC_FRAME_ADDRESS;
    UARTx->tx_buffer[2] = ANOTC_FRAME_FLEXIBLE;

    // Add data
    //  UARTx->tx_buffer[cnt++] = data1;
    //  UARTx->tx_buffer[cnt++] = data2;
    //  UARTx->tx_buffer[cnt++] = data3;
    cnt = Anotc_ProcessSentData(UARTx, cnt);
    // Set data length
    UARTx->tx_buffer[3] = cnt - ANOTC_PROTOCOL_HEADER_SIZE;

    // Calculate checksum
    for (i = 0; i < cnt; i++) {
        sumcheck += UARTx->tx_buffer[i];
        addcheck += sumcheck;
    }

    // Add checksum to protocol
    UARTx->tx_buffer[cnt++] = sumcheck;
    UARTx->tx_buffer[cnt++] = addcheck;

    // Set sending status
    UARTx->tx_index  = 0;
    UARTx->tx_length = cnt;

    // // Send data to UART
    // while (UARTx->tx_index < UARTx->tx_length) {
    //     ct_uart_SendBuff(UARTx, UARTx->tx_buffer[UARTx->tx_index++]);
    //     while (UARTx->tx_bBusy)
    //         ;
    // }

    // Start sending the first byte to trigger the interrupt-driven transmission
    ct_uart_SendBuff(UARTx, UARTx->tx_buffer[UARTx->tx_index++]);
    UARTx->tx_bBusy = 1;
}

typedef enum {
    WAIT_FOR_HEADER,
    WAIT_FOR_ADDRESS,
    WAIT_FOR_LENGTH,
    WAIT_FOR_DATA,
} UART_STATE;

void Anotc_ReadFrame(UART_t *UARTx) {
    static UART_STATE state    = WAIT_FOR_HEADER;
    uint8_t           sumcheck = 0;
    uint8_t           addcheck = 0;
    uint8_t           receivedSumCheck, receivedAddCheck;
    uint8_t           i;
    bool              shouldContinue = true;
    // Check parameters to ensure not a NULL pointer
    if (UARTx == NULL) {
        return;
    }

    // Check for timeout
    if (UARTx->rx_index > 0) {
        if (UARTx->rx_timeout < ANOTC_RESPONSE_TIMEOUT) {
            UARTx->rx_timeout++;
        } else {
            UARTx->rx_bTimeout = 1;    // set timeout flag
            //
            UARTx->rx_index = 0;
            state           = WAIT_FOR_HEADER;
        }
    }

    // Check if enough data has been received before processing
    if (UARTx->rx_index < 4) {
        return;
    }

    // Check for overflow error
    if (UARTx->rx_bOverflow) {
        UARTx->rx_bOverflow = 0;
        state               = WAIT_FOR_HEADER;
        UARTx->rx_index     = 0;
        return;
    }

    while (shouldContinue) {
        shouldContinue = false;    // default don't continue

        switch (state) {
            case WAIT_FOR_HEADER:
                if (UARTx->rx_buffer[0] != ANOTC_FRAME_HEADER) {
                    // Handle header error
                    // HandleHeaderError(UARTx);
                    UARTx->rx_index = 0;
                } else {
                    state          = WAIT_FOR_ADDRESS;
                    shouldContinue = true;    // next state
                }
                break;

            case WAIT_FOR_ADDRESS:
                if (UARTx->rx_buffer[1] != ANOTC_FRAME_ADDRESS) {
                    // Handle address error
                    // HandleAddressError(UARTx);
                    UARTx->rx_index = 0;
                    state           = WAIT_FOR_HEADER;
                } else {
                    state          = WAIT_FOR_LENGTH;
                    shouldContinue = true;    // next state
                }
                break;

            case WAIT_FOR_LENGTH:
                if (UARTx->rx_buffer[3] > ANOTC_FRAME_LENGTH_MAX) {
                    // Handle length error
                    // HandleLengthError(UARTx);
                    UARTx->rx_index = 0;
                    state           = WAIT_FOR_HEADER;
                } else {

                    UARTx->rx_length  = UARTx->rx_buffer[3] + ANOTC_PROTOCOL_HEADER_SIZE + ANOTC_CHECKSUM_SIZE;
                    UARTx->rx_timeout = 0;
                    state             = WAIT_FOR_DATA;
                    shouldContinue    = true;    // next state
                }
                break;
            case WAIT_FOR_DATA:
                if (UARTx->rx_index >= UARTx->rx_length) {
                    UARTx->rx_bLock = 1;
                    // Calculate checksum for the received data
                    for (i = 0; i < UARTx->rx_length - ANOTC_CHECKSUM_SIZE; i++) {
                        sumcheck += UARTx->rx_buffer[i];
                        addcheck += sumcheck;
                    }

                    // Get the received checksum
                    receivedSumCheck = UARTx->rx_buffer[UARTx->rx_length - ANOTC_CHECKSUM_SIZE];
                    receivedAddCheck = UARTx->rx_buffer[UARTx->rx_length - ANOTC_CHECKSUM_SIZE + 1];

                    // Verify checksum
                    if (sumcheck == receivedSumCheck && addcheck == receivedAddCheck) {
                        // Checksum is correct, process data

                        Anotc_ProcessReceivedData(UARTx);

                    } else {
                        // Checksum is incorrect, handle error situation
                        //  HandleChecksumError();
                    }

                    // Reset rx_bLock flag for the next frame
                    UARTx->rx_bLock = 0;
                    UARTx->rx_index = 0;
                    state           = WAIT_FOR_HEADER;
                } else {
                    if (++UARTx->rx_timeout > ANOTC_TIMEOUT_CNT) {
                        // Timeout occurred, reset receive state
                        UARTx->rx_index   = 0;
                        UARTx->rx_timeout = 0;
                        UARTx->rx_bLock   = 0;
                    }
                }
                break;

            default:
                state = WAIT_FOR_HEADER;
                break;
        }
    }
}

void Anotc_ProcessReceivedData(UART_t *UARTx) {

    if (UARTx->rx_buffer[2] == ANOTC_FRAME_UPPER_READ) {
        // Upper need to read data, send data

    } else if (UARTx->rx_buffer[2] == ANOTC_FRAME_UPPER_WRITE) {
        // Upper write data to lower, receive data
    }
}

#endif
